/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package ihmprojet.core.model;

import edu.uci.ics.jung.graph.DelegateTree;
import edu.uci.ics.jung.graph.util.Pair;
import ihmprojet.core.model.exception.GraphOperatorNotFoundException;
import ihmprojet.core.model.operateur.OperateurBinaire;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

/**
 *
 * @author Rémi PIOTAIX <remi.piotaix@gmail.com>
 */
public class DelegateTreeOperators<V extends Sommet, E> extends DelegateTree<V, E> {

    private HashMap<V, GraphOperator<V, ArreteOperateur>> sourceIdx = new HashMap<>();

    public void addOperateur(V source, V cible, String operateur) {
        addOperateur(source, cible, new OperateurBinaire(operateur));
    }

    public void addOperateur(V source, V cible, OperateurBinaire ob) {
        if (!containsVertex(cible) || !containsVertex(source)) {
            throw new RuntimeException("Un des somments n'est pas dans le graphe");
        }
//        if (source.getOperateurSource() != null) {
//            throw new RuntimeException("source deja la source d'un operateur binaire");
//        }
//        if (cible.getOperateurCible() != null) {
//            throw new RuntimeException("Cible deja la cible d'un operateur binaire");
//        }

        GraphOperator<V, ArreteOperateur> go = new GraphOperator(source, cible, new ArreteOperateur(ob));
        sourceIdx.put(source, go);
    }

    public void removeOperateurBySource(V source) {
        GraphOperator<V, ArreteOperateur> go = sourceIdx.remove(source);
    }

    public OperateurBinaire getOperateurBySource(V source) {
        GraphOperator<V, ArreteOperateur> go = sourceIdx.get(source);
        return go == null ? null : go.getEdge().getOb();
    }

    public V getCibleOperateurBinaire(V source) {
        GraphOperator<V, ArreteOperateur> go = sourceIdx.get(source);
        return go == null ? null : go.getCible();
    }

    @Override
    public String toString() {
        return super.toString() + "\n" + sourceIdx + "\n";
    }

    public Map<V, GraphOperator<V, ArreteOperateur>> getOperateurs() {
        return Collections.unmodifiableMap(sourceIdx);
    }

    /**
     *
     * @param edge
     * @return
     */
    private GraphOperator<V, ArreteOperateur> getGraphOperateur(E edge) {
        for (V vertex : sourceIdx.keySet()) {
            GraphOperator<V, ArreteOperateur> go = sourceIdx.get(vertex);
            if (go.getEdge() == edge) {
                return go;
            }
        }

        throw new GraphOperatorNotFoundException(edge.toString());
    }

    @Override
    public Pair<V> getEndpoints(E edge) {
        if (edge instanceof ArreteOperateurInterface) {
            GraphOperator<V, ArreteOperateur> go = getGraphOperateur(edge);

            return new Pair<>(go.getSource(), go.getCible());
        } else {
            return super.getEndpoints(edge);
        }
    }
}
